﻿/*
 * Portions Copyright 2010 Andrew Bolson, Unknown License 
 *   (http://www.codeproject.com/Members/Andrew-Boisen)
 * ----- - - - - - - -- -- -- -- -- -- -- -- -- -- -- - - - - - - -----
 * Other Portions Copyright 2011 John M. Hollingsworth
 *   (http://www.jmhollingsworth.us/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Timers;
using System.Text;
using System.Threading;
using System.Windows.Forms;

using EggTimerWithStatus;

using log4net;

namespace EggTimerWithStatus
{
    public partial class EggTimerForm : Form
    {
        private ILog Log = null;
        private Properties.Settings settings = null;
        private System.Timers.Timer timerClock = new System.Timers.Timer();
        private int clockTime = 0;
        private int alarmTime = 0;
        private FlashWindowWrapper fw = null;
        public enum LogLevels
        {
            FATAL,
            ERROR,
            WARN,
            INFO,
            DEBUG
        }

        public EggTimerForm()
        {
            InitializeComponent();
            InitializeSettings();
            InitializeLogger();
            InitializeTimer();
        }

        private void InitializeSettings() 
        {
            settings = new Properties.Settings();
            fw = new FlashWindowWrapper();
        }

        private void InitializeLogger() 
        {
            if (settings.LoggingEnabled)
            {
                Logger logger = Logger.Instance;
                if (logger != null)
                {
                    if (settings.Log4netConfigPath.Equals(string.Empty))
                    {
                        Logger.Configure("C:\\Users\\John\\documents\\visual studio 2010\\Projects\\EggTimerWithStatus\\EggTimerWithStatus\\loggingConfiguration.xml");
                    }
                    else
                    {
                        Logger.Configure(settings.Log4netConfigPath);
                    }
                }
                this.Log = logger.Log;
                StringBuilder sb = new StringBuilder("\n");
                sb.Append("  -------------------------------------------------\n");
                sb.Append("  -             Egg Timer With Status             -\n");
                sb.Append("  -------------------------------------------------");

                this.Log.Info(sb.ToString());
            }
        }

        private void InitializeTimer() 
        { 
            this.timerClock.Elapsed += new ElapsedEventHandler(OnTimer);
            this.timerClock.Interval = 1000;
            this.timerClock.Enabled = false;
            this.Log.Debug("Timer Initialized at an interval of " + this.timerClock.Interval);
        }

        public delegate void TimerChange(Object source, ElapsedEventArgs e);

        public void OnTimer(Object source, ElapsedEventArgs e)
        {
            try 
            {
                if (this.timerInput.InvokeRequired)
                {
                    TimerChange timeChange = new TimerChange(OnTimer);
                    this.Invoke(timeChange, new object[] { source, e });
                }
                else
                {
                    this.clockTime++;
                    int countdown = this.alarmTime - this.clockTime;
                    if (this.alarmTime != 0)
                    {
                        this.timerInput.Text = secondsToTime(countdown);
                    }

                    // "Sound" alarm
                    if (this.clockTime == this.alarmTime)
                    {
                        LogWrapper(LogLevels.INFO, "TIME'S UP");
                        fw.FlashWindow(FlashWindowWrapper.FlashFlags.FLASHW_ALL, this.Handle);
                    }
                }
            }
            catch (Exception ex) 
            {
                MessageBox.Show("OnTimer(): " + ex.Message);
            }
        }

        private void inputToSeconds(string timerInput)
        {
            try
            {
                string[] timeArray = new string[3];
                int minutes = 0;
                int hours = 0;
                int seconds = 0;
                int occurence = 0;
                int length = 0;

                occurence = timerInput.LastIndexOf(":");
                length = timerInput.Length;

                // Check for valid input
                if (occurence == -1 || length != 8)
                {
                    MessageBox.Show("Invalid Time Format.");
                    ResetButton_Click(null, null);
                }
                else
                {
                    timeArray = timerInput.Split(':');

                    seconds = Convert.ToInt32(timeArray[2]);
                    minutes = Convert.ToInt32(timeArray[1]);
                    hours = Convert.ToInt32(timeArray[0]);

                    this.alarmTime += seconds;
                    this.alarmTime += minutes * 60;
                    this.alarmTime += (hours * 60) * 60;
                }
            }
            catch (Exception e)
            {
                MessageBox.Show("inputToSeconds(): " + e.Message);
            }
        }

        public string secondsToTime(int seconds)
        {
            int minutes = 0;
            int hours = 0;

            while (seconds >= 60)
            {
                minutes += 1;
                seconds -= 60;
            }
            while (minutes >= 60)
            {
                hours += 1;
                minutes -= 60;
            }

            string strHours = hours.ToString();
            string strMinutes = minutes.ToString();
            string strSeconds = seconds.ToString();

            if (strHours.Length < 2)
                strHours = "0" + strHours;
            if (strMinutes.Length < 2)
                strMinutes = "0" + strMinutes;
            if (strSeconds.Length < 2)
                strSeconds = "0" + strSeconds;

            return strHours + ":" + strMinutes + ":" + strSeconds;
        }

        private void LogWrapper(LogLevels Level, string message)
        {
            if (settings.LoggingEnabled)
            {
                switch (Level)
                {
                    case LogLevels.FATAL:
                        this.Log.Fatal(message);
                        break;
                    case LogLevels.WARN:
                        this.Log.Warn(message);
                        break;
                    case LogLevels.INFO:
                        this.Log.Info(message);
                        break;
                    case LogLevels.DEBUG:
                        this.Log.Debug(message);
                        break;
                    case LogLevels.ERROR:
                    default:
                        this.Log.Error(message);
                        break;
                }
            }
            else
            {
                MessageBox.Show(message);
            }
        }

        private void StartButton_Click(object sender, EventArgs e)
        {
            this.clockTime = 0;
            inputToSeconds(this.timerInput.Text);
            this.timerClock.Enabled = true;
            LogWrapper(LogLevels.DEBUG, "StartButton_Click()");
        }

        private void BreakButton_Click(object sender, EventArgs e)
        {
            try
            {
                this.clockTime = 0;
                this.alarmTime = 0;
                this.timerInput.Text = "00:05:00";
                inputToSeconds(this.timerInput.Text);
                this.timerClock.Enabled = true;
                LogWrapper(LogLevels.INFO, "BreakButton_Click()");
            }
            catch (Exception ex)
            {
                LogWrapper(LogLevels.ERROR, "BreakButton_Click(): " + ex.Message);
            }
        }

        private void ResetButton_Click(object sender, EventArgs e)
        {
            try
            {
                this.clockTime = 0;
                this.alarmTime = 0;
                this.timerInput.Text = "00:55:00";
                fw.FlashWindow(FlashWindowWrapper.FlashFlags.FLASHW_STOP, this.Handle);
                LogWrapper(LogLevels.INFO, "ResetButton_Click()");
            }
            catch (Exception ex)
            {
                LogWrapper(LogLevels.ERROR, "ResetButton_Click(): " + ex.Message);
            }
        }

        private void StatusButton_Click(object sender, EventArgs e)
        {
            try
            {
                //refactor
                StatusEntryForm seForm = new StatusEntryForm();
                seForm.Show();
                LogWrapper(LogLevels.INFO, "StatusButton_Click()");
            }
            catch (Exception ex)
            {
                LogWrapper(LogLevels.ERROR, "StatusButton_Click(): " + ex.Message);
            }
        }
    }
}
